package com.ejlchina.tool

import android.annotation.SuppressLint
import android.app.DownloadManager
import android.bluetooth.BluetoothGatt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.ui.setupWithNavController
import com.adolf.androiddemo.R
import com.adolf.androiddemo.databinding.ActivityMainBinding
import com.ejlchina.tool.base.BaseBindingActivity
import com.ejlchina.tool.bean.BleDeviceBean
import com.ejlchina.tool.bean.Command
import com.ejlchina.tool.bean.VersionResBean
import com.ejlchina.tool.constant.DEVICE_MODE_NO_SELECT
import com.ejlchina.tool.constant.SP_DEVICE_MODE
import com.ejlchina.tool.enums.FirmwareUpgradeResultEnum
import com.ejlchina.tool.fragment.dialog.VersionCheckDialogFragment
import com.ejlchina.tool.network.NetApi
import com.ejlchina.tool.singleton.GlobalAction
import com.ejlchina.tool.singleton.GlobalConnectObject
import com.ejlchina.tool.singleton.GlobalParams
import com.ejlchina.tool.singleton.SharedPreferenceUtil
import com.ejlchina.tool.util.COMMAND_LIGHT_TIME_SET_DOWNWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD
import com.ejlchina.tool.util.COMMAND_UPLOAD_FILE
import com.ejlchina.tool.util.CRC16_MODBUS
import com.ejlchina.tool.util.LOG_TAG
import com.ejlchina.tool.util.RELOAD_AND_UPGRADE_DOWNLOAD
import com.ejlchina.tool.util.SUB_COMMAND_1
import com.ejlchina.tool.util.bytearray.intTo16HexStringLE
import com.ejlchina.tool.util.bytearray.intTo32HexStringLE
import com.ejlchina.tool.util.bytearray.intToByteHexString
import com.ejlchina.tool.util.bytearray.toHexString
import com.ejlchina.tool.util.getStatusBarHeight
import com.ejlchina.tool.util.showToast
import com.ejlchina.tool.util.timestamp
import com.ejlchina.tool.util.transparentStatusBar
import com.huyuhui.fastble.BleManager
import com.huyuhui.fastble.data.BleDevice
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileInputStream
import java.math.BigDecimal
import java.math.RoundingMode


class MainActivity : BaseBindingActivity<ActivityMainBinding>() {

    private lateinit var navController: NavController
    private val restoreDataListMap = mutableMapOf<String,MutableList<Command>>()
    private val checkVersionDialog: VersionCheckDialogFragment = VersionCheckDialogFragment()
    var firmwareDownloadId = -1L
    private val downloadReceiver = object : BroadcastReceiver(){
        override fun onReceive(context: Context, intent: Intent) {
            when(intent.action){
                DownloadManager.ACTION_DOWNLOAD_COMPLETE -> {
                    if (this@MainActivity.firmwareDownloadId == intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)){
                        showToast("升级文件下载完成，正在传输文件", duration = Toast.LENGTH_LONG)
                        handleUpgrade()
                    }
                }
                DownloadManager.ACTION_NOTIFICATION_CLICKED -> {
                    showToast("dianji", duration = Toast.LENGTH_LONG)
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initData()
        initView()
        initObservers()
        checkVersion()
    }


    fun openDraw(){
        binding.drawer.openDrawer(binding.drawMenu,true)
    }

    private fun closeDraw(){
        binding.drawer.closeDrawer(binding.drawMenu,true)
    }

    private fun initData(){
        registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), RECEIVER_EXPORTED)
    }

    private fun initObservers(){
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED){

                launch {
                    GlobalAction.notifyResultFlow.collect{
                        initRestoreData(it.bleDevice.bleDevice)
                    }
                }

                launch {
                    GlobalAction.disConnectFlow.collect{ bleDevice ->
                        showToast("设备${bleDevice.mac}已断开连接")
                        removeRestoreDevice(bleDevice)
//                        GlobalParams.firmwareUpgradeList.find { it.bleDevice.mac == bleDevice.mac }?.let {
//                            if (it.upgradeResult < 100){
//                                it.upgradeResult = -1F
//                                GlobalAction.firmwareUpgradeMap[bleDevice.mac]?.tryEmit(true)
//                            }
//                        }
                    }
                }
            }
        }
    }

    private fun initRestoreData(bleDevice: BleDevice) {
        restoreDataListMap[bleDevice.mac] = mutableListOf(
            Command(0, COMMAND_LIGHT_TIME_SET_DOWNWARD, ""),
            Command(0, COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD, ""),
            Command(1, COMMAND_LIGHT_TIME_SET_DOWNWARD, ""),
            Command(1, COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD, ""),
            Command(2, COMMAND_LIGHT_TIME_SET_DOWNWARD, ""),
            Command(2, COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD, "")
        )
    }

    private fun removeRestoreDevice(bleDevice: BleDevice){
        restoreDataListMap.remove(bleDevice.mac)
    }

    fun saveData(pageIndex: Int, bleDevice: BleDevice, command: String, dataString: String){
        restoreDataListMap[bleDevice.mac]?.let { commandList ->
            commandList.filter { it.pageIndex == pageIndex }.let { commandList ->
                commandList.find { it.commandString == command }?.let {
                    if (it.commandData.isEmpty()){
                        it.commandData = dataString
                    }
                }
            }
        }
        Log.i(LOG_TAG,"保存-${pageIndex}---${restoreDataListMap}")
    }

    fun restoreData(pageIndex: Int) {
        for (deviceMac in restoreDataListMap.keys) {
            restoreDataListMap[deviceMac]?.let { commandList ->
                commandList.filter { it.pageIndex == pageIndex }.let { filterList ->
                    Log.i(LOG_TAG, "恢复---${pageIndex} -- ${deviceMac}--$commandList")
                    for (command in filterList) {
                        GlobalConnectObject.getDeviceFromMac(deviceMac)?.let {
                            if (command.commandData.isNotEmpty()) {
                                setCommandData(it, command.commandString, command.commandData, isForFireUpload = false, isShowLoading = false
                                )
                            }
                        }
                    }
                }
            }
        }
    }

    fun restoreData(pageIndex: Int,mac: String){
        lifecycleScope.launch {
            for (deviceMac in restoreDataListMap.keys){
                if (deviceMac != mac) continue
                restoreDataListMap[deviceMac]?.let { commandList ->
                    commandList.filter { it.pageIndex == pageIndex }.let { filterList ->
                        for (command in filterList){
                            GlobalConnectObject.getDeviceFromMac(deviceMac)?.let {
                                if (command.commandData.isNotEmpty()){
                                    Log.i(LOG_TAG,"@@@@@@@@@@@@@@@@@@${command}")
                                    setCommandData(it,command.commandString,command.commandData, isForFireUpload = false, isShowLoading = false)
                                    delay(400)
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    fun restoreDataExcept(pageIndex: Int,mac: String){
        lifecycleScope.launch {
            for (deviceMac in restoreDataListMap.keys){
                if (deviceMac == mac) continue
                restoreDataListMap[deviceMac]?.let { commandList ->
                    commandList.filter { it.pageIndex == pageIndex }.let { filterList ->
                        for (command in filterList){
                            GlobalConnectObject.getDeviceFromMac(deviceMac)?.let {
                                if (command.commandData.isNotEmpty()){
                                    Log.i(LOG_TAG,"@@@@@@@@@@@@@@@@@@${command}")
                                    setCommandData(it,command.commandString,command.commandData, isForFireUpload = false, isShowLoading = false)
                                    delay(400)
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    fun clearAllSaveData(pageIndex: Int,){
        for (deviceMac in restoreDataListMap.keys){
            restoreDataListMap[deviceMac]?.let { commandList ->
                commandList.filter { it.pageIndex == pageIndex }.let {
                    for (command in it){
                        command.commandData = ""
                    }
                }
            }
        }
    }

    fun clearAllSaveDataByMac(pageIndex: Int,mac: String){
        for (deviceMac in restoreDataListMap.keys){
            if (deviceMac == mac){
                restoreDataListMap[deviceMac]?.let { commandList ->
                    commandList.filter { it.pageIndex == pageIndex }.let {
                        for (command in it){
                            command.commandData = ""
                        }
                    }
                }
            }
        }
    }

    fun handleUpgrade(){
        lifecycleScope.launch {
            for ((index,item) in GlobalParams.firmwareUpgradeList.withIndex()){
                if (item.isReadToUpgrade()){
                    delay(2000) //这个延迟时间是为了在多个设备固件升级完成之后，设备断开连接的flow同时发送会有的收不到的情况
                    uploadFile2(item)
                }
            }
        }
    }

    private fun checkVersion(needLoading: Boolean = false) {
        if (needLoading) {
            showLoading()
        }
        NetApi.getVersion {
            dismissLoading()
            it?.let { versionResBean ->
                lifecycleScope.launch {
                    if (packageManager.getPackageInfo(packageName, 0).versionCode < versionResBean.code) {
                        checkVersionDialog.updateInfo = versionResBean
                        checkVersionDialog.show(supportFragmentManager, LOG_TAG)
                    } else {
                        if (needLoading) {
                            showToast("已经是最新版本")
                        }
                    }
                    Log.i(LOG_TAG, versionResBean.toString())
                }
            }
        }
    }

    private fun handleVersionUpdate(versionResBean: VersionResBean){

    }

    private fun handleFileUploadResult(device: BleDeviceBean, dataByteArray: ByteArray) {
        val result = dataByteArray[dataByteArray.size - 1].toInt()
        if (result == FirmwareUpgradeResultEnum.SUCCESS.resultCode) {
            reloadToUpgrade(device)
        } else {
            showToast(FirmwareUpgradeResultEnum.getResultStringFromResultCode(result).resultString)
        }
    }

    @SuppressLint("MissingPermission", "SetTextI18n")
    private fun initView(){
        initActionBar()
        navController = findNavController(R.id.nav_host_fragment)
        binding.bottomNav.setupWithNavController(navController)

        navController.addOnDestinationChangedListener{ controller, destination, arguments ->
            when(destination.id){
                R.id.debugFragment,
                R.id.configFragment -> {
                    binding.bottomNav.visibility = View.VISIBLE
                }
                else -> binding.bottomNav.visibility = View.GONE
            }
        }

        val control = WindowCompat.getInsetsController(window, binding.root)
        control.isAppearanceLightStatusBars = true

        binding.layoutChangeMode.setOnClickListener {
            SharedPreferenceUtil.putInt(SP_DEVICE_MODE, DEVICE_MODE_NO_SELECT)
            navController.navigate(R.id.action_global_device_mode)
            closeDraw()
        }

        binding.tvVersionName.text = "版本号：V${packageManager.getPackageInfo(packageName,0).versionName}"
        binding.layoutCheckNewVersion.setOnClickListener {
            checkVersion(true)
            closeDraw()
        }
    }
    
    private fun initActionBar(){
        getStatusBarHeight(this)
        transparentStatusBar(window)
    }

    fun setBottomViewMenuEnable(index: Int,isEnable: Boolean){
//        binding.bottomNav.menu.getItem(index).isEnabled = isEnable
    }

    private fun getFileInfoCommand(uploadFileByteArray: ByteArray,currentIndex: Int, currentFileByteArray: ByteArray): String{
        val allFileSize = uploadFileByteArray.size
        val commandStringBuffer = StringBuffer()
        commandStringBuffer.append("01") //TYPE 固件文件
        commandStringBuffer.append(intTo32HexStringLE(allFileSize)) //FLSZ 字段：文件大小，单位：字节。无符号 32 位整型。
        commandStringBuffer.append(getCrcString(uploadFileByteArray)) // FLCRC 字段：整个文件的 CRC16 校验值，使用 CRC-16/MODBUS。无符号十六位整型。

        val isHasRemainder = (allFileSize % 128) > 0
        val pgTotal = allFileSize / 128 + (if (isHasRemainder) 1 else 0)
        commandStringBuffer.append(intTo16HexStringLE(pgTotal)) //PGTOTAL 字段：文件总包数。无符号 16 位整型。
        commandStringBuffer.append(intTo16HexStringLE(currentIndex)) // PGIDX 字段：当前传输的文件包 IDX，无符号十六位整型
        commandStringBuffer.append(getCrcString(currentFileByteArray)) // PGCRC 字段：当前数据包（PGDATA 内容）的 CRC16 校验值无符号十六位整型。
        commandStringBuffer.append(intTo16HexStringLE(currentFileByteArray.size)) //PGSZ 字段：当前传输的文件包长度,无符号十六位整型
        commandStringBuffer.append(currentFileByteArray.toHexString(false))
        return commandStringBuffer.toString()
    }

    private fun getCompleteCommand(bleDevice: BleDevice, uploadFileByteArray: ByteArray, currentIndex: Int, currentFileByteArray: ByteArray): String{
        val finalCommand = StringBuffer()
        finalCommand.append(COMMAND_UPLOAD_FILE)
        val fileCommandString = getFileInfoCommand(uploadFileByteArray, currentIndex, currentFileByteArray)
        finalCommand.append(intToByteHexString(15 + currentFileByteArray.size + 1))
        finalCommand.append(SUB_COMMAND_1)
        finalCommand.append(fileCommandString)
        finalCommand.append(timestamp())
        finalCommand.append(SharedPreferenceUtil.getString(bleDevice.mac))
        return finalCommand.toString()
    }


    @SuppressLint("MissingPermission")
    private fun uploadFile(device: BleDeviceBean) {
        lifecycleScope.launch(Dispatchers.IO) {
            val updateFile = getVersionFile("${device.upgradeToVersion}.bin")
            if (updateFile == null) {
                showToast("未找到升级文件")
            } else {
                val fileByteArray = updateFile.readBytes()
                val isHasRemainder = (updateFile.length() % 128) > 0
                val pgTotal = (updateFile.length() / 128 + (if (isHasRemainder) 1 else 0)).toInt() //文件总包数
                val bytes = ByteArray(128)
                FileInputStream(updateFile).use { it ->
                    var len: Int
                    var count: Int = -1
                    while (((it.read(bytes)).also { len = it }) != -1) {
                        count++
                        val result = getCompleteCommand(device.bleDevice,fileByteArray,count,bytes.copyOfRange(0,len))
                        Log.i(LOG_TAG,"总次数${pgTotal}--发送----第${count + 1}次---每次${len}字节--内容为:${result}")

                        if (BleManager.isConnected(device.bleDevice.mac)) {
                            GlobalParams.firmwareUpgradeList.find { it.bleDevice.mac == device.bleDevice.mac }?.let { upgradeDevice ->
                                upgradeDevice.upgradeResult = getProgress((count + 1) / pgTotal.toDouble())
                            }
                            GlobalAction.firmwareUpgradeMap[device.bleDevice.mac]?.tryEmit(true)
                            viewModel.writeFile(device, result)
                            delay(120)
                        } else {
                            GlobalParams.firmwareUpgradeList.find { it.bleDevice.mac == device.bleDevice.mac }?.let { upgradeDevice ->
                                upgradeDevice.upgradeResult = -1F
                            }
                            GlobalAction.firmwareUpgradeMap[device.bleDevice.mac]?.tryEmit(true)
                            break
                        }
                    }

                }
            }
        }
    }


    @SuppressLint("MissingPermission")
    private fun uploadFile2(device: BleDeviceBean) {
        lifecycleScope.launch(Dispatchers.IO) {
            val updateFile = getVersionFile("${device.upgradeToVersion}.bin")
            if (updateFile == null) {
                showToast("未找到升级文件")
            } else {
                val fileByteArray = updateFile.readBytes()
                val isHasRemainder = (updateFile.length() % 128) > 0
                val pgTotal = (updateFile.length() / 128 + (if (isHasRemainder) 1 else 0)).toInt()  //文件总包数
                val buffer = ByteArray(128)
                FileInputStream(updateFile).use { it ->
                    for (item in 0 until pgTotal) {
                        val count = it.read(buffer)
                        val result = getCompleteCommand(device.bleDevice, fileByteArray, item, buffer.copyOfRange(0, count))
                        Log.i(LOG_TAG, "总次数${pgTotal}--发送----第${item + 1}次---每次${count}字节--内容为:${result}")
                        if (BleManager.isConnected(device.bleDevice.mac)) {
                            Log.i(LOG_TAG, "这个是确认设备已连接--${device.bleDevice.mac}")
                            GlobalParams.firmwareUpgradeList.find { it.bleDevice.mac == device.bleDevice.mac }?.let { upgradeDevice ->
                                upgradeDevice.upgradeResult = getProgress((item + 1) / pgTotal.toDouble())
                            }
                            GlobalAction.firmwareUpgradeMap[device.bleDevice.mac]?.tryEmit(true)
                            viewModel.writeFile(device, result)
                            delay(150)
                        } else {
                            GlobalParams.firmwareUpgradeList.find { it.bleDevice.mac == device.bleDevice.mac }?.let { upgradeDevice ->
                                upgradeDevice.upgradeResult = -1F
                            }
                            GlobalAction.firmwareUpgradeMap[device.bleDevice.mac]?.tryEmit(true)
                            break
                        }
                    }
                }
            }
        }
    }

    private fun getProgress(progress: Double): Float{
        return BigDecimal(progress * 100).setScale(1,RoundingMode.FLOOR).toFloat()
    }

    private fun reloadToUpgrade(device: BleDeviceBean) {
        setCommandData(device,RELOAD_AND_UPGRADE_DOWNLOAD, "01", isForFireUpload = false, isShowLoading = true)
    }

    private fun getVersionFile(name: String): File?{
        val versionDownloadFile = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
        return versionDownloadFile?.let {
            if (it.listFiles().isNotEmpty()){
                it.listFiles()?.get(0)
            } else {
                null
            }

        }
    }

    private fun getCrcString(byteArray: ByteArray): String{
        return intTo16HexStringLE(CRC16_MODBUS(byteArray))
    }

    override fun onBackPressed() {
        navController.currentDestination?.let { currentDestination ->
            if (currentDestination.id == R.id.debugFragment || currentDestination.id == R.id.configFragment){
                finish()
            }else {
                super.onBackPressed()
            }
        } ?: run {
            super.onBackPressed()
        }
    }

    override fun getViewBinding(): ActivityMainBinding {
        return ActivityMainBinding.inflate(layoutInflater)
    }

    @SuppressLint("MissingPermission")
    override fun onDestroy() {
        super.onDestroy()
        Log.i(LOG_TAG,"MainActivity OnDestroy")
        GlobalScope.launch {
            delay(600) //这里的Delay是为了保证退出之前的一些指令发送，比如fragment中的onDestroyView或onDestroy
            BleManager.disconnectAllDevice()
            GlobalConnectObject.getCurrentConnectDeviceList().clear()
        }
    }
}